import { useRef, useEffect } from 'react';
import { parse } from 'qs';

import { message, notification } from 'antd';
import cookie from 'js-cookie';
import { formatMessage } from 'umi';
import moment from 'moment';
import authHelper from '@/utils/auth/helper';
import pageTabUtil from '@/utils/pageTabUtil';
import Authorized from '@/utils/Authorized';

export * from '@/utils/renderFormUtils';

const { check } = Authorized;

import * as FileSaver from 'file-saver';

// 暂时隐藏薪资参考表格，后期要展示的话把以下值改为false即可
export const hideSalaryTable = true;

const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)$/;

export function isUrl(path) {
    return reg.test(path);
}
export function isPhone() {
    return window.innerWidth < 800;
}
export const getTreeData = (data, fieldsName = { value: 'id', title: 'departmentName' }) =>
    data.map(item => ({
        ...item,
        value: item[fieldsName.value],
        title: item[fieldsName.title],
        key: item[fieldsName.value],
        children: item.children ? getTreeData(item.children, fieldsName) : item.children
    }));

export function getPageQuery() {
    return parse(window.location.href.split('?')[1]);
}

/**
 * 删除空的children节点
 * @param data
 * @returns {*}
 */
export function deleteNullChildren(data) {
    return data.map(item => {
        const result = Object.assign({}, item);
        if (item.children) {
            if (item.children.length > 0) {
                result.children = deleteNullChildren(item.children);
            } else {
                delete result.children;
            }
        }
        return result;
    });
}

/**
 * 传入分钟转为X天X小时X分钟
 * @param {number} str 分钟
 * @param {number} hourlySystem 小时制 默认24小时制
 */
export function dateConversion(str, hourlySystem) {
    let num;
    if (hourlySystem) {
        num = hourlySystem;
    } else {
        num = 24;
    }
    if (!str) {
        return `0${formatMessage({ id: 'stat.hour' })}0${formatMessage({
            id: 'stat.minute'
        })}`;
    }
    const days = Math.floor(str / num / 60).toString();
    let hours;
    const minutes = (str % 60).toString();
    if (days > 0) {
        const str1 = str - days * (num * 60);
        hours = Math.floor(str1 / 60).toString();
    } else {
        hours = Math.floor(str / 60).toString();
    }

    const handleText = (value, unit) => (Number(value) ? value + unit : '');

    const result = [
        handleText(
            days,
            formatMessage({
                id: 'stat.day'
            })
        ),
        handleText(
            hours,
            formatMessage({
                id: 'stat.hour'
            })
        ),
        handleText(
            minutes.length < 2 ? `0${minutes}` : minutes,
            formatMessage({
                id: 'stat.minute'
            })
        )
    ];
    return result.join('') || 0;
}

/**
 * 传入分钟转为X小时X分钟
 * @param {number} str 分钟
 */
export function dateConversion2(str) {
    if (!str) {
        return `0${formatMessage({ id: 'stat.hour' })}0${formatMessage({
            id: 'stat.minute'
        })}`;
    }
    const minutes = (str % 60).toString();
    const hours = Math.floor(str / 60).toString();

    const handleText = (value, unit) => (Number(value) ? value + unit : '');

    const result = [
        handleText(
            hours,
            formatMessage({
                id: 'stat.hour'
            })
        ),
        handleText(
            minutes.length < 2 ? `0${minutes}` : minutes,
            formatMessage({
                id: 'stat.minute'
            })
        )
    ];
    return result.join('') || 0;
}

/**
 * 路由字段更改
 * @param data
 * @returns {*}
 */
export const change = data =>
    data.map(item => ({
        ...item,
        path: item.url,
        name: item.menuName,
        root: item.parentMenuId === 0,
        children: item.children.length > 0 ? [...change(item.children)] : []
    }));

export const checkAuthCode = (code, authData = []) => {
    const result = (Array.isArray(authData) && authData.some(item => item.code === code)) || code === true;
    if (!result) console.log('无权限code：', code);
    return result;
};

export const find = (routes = [], data, tmpRoutes, level = 1) => {
    routes.forEach(item => {
        if (!item.redirect && item.path && checkAuthCode(item.code, data)) {
            const a = {
                ...item,
                routes: []
            };
            if (item.routes) {
                find(item.routes, data, a.routes, level + 1);
            }
            tmpRoutes.push(a);
        } else if (item.path) {
            console.log('无权限路由：', item.path);
        }
    });
};

/**
 * 转换小数位百分比并显示两位数
 * @param point
 * @returns {string}
 */
export function toPercent(point, showPercent = true) {
    let str = Number(point * 100).toFixed(2);
    if (showPercent) str += '%';
    return str;
}

export function renderTopMenu(menuData) {
    let level;

    const getSubMenu = (item, curLevel) => {
        if (curLevel === 1) {
            level = item.menuLevel;
        }

        const subMenuFn = () =>
            item.children.map(it => ({
                ...it,
                children: getSubMenu(it, curLevel + 1)
            }));

        return curLevel > level ? [] : subMenuFn();
    };

    return menuData.map(item => ({
        ...item,
        children: getSubMenu(item, 1)
    }));
}

export function usePrevious(value) {
    const ref = useRef();
    useEffect(() => {
        ref.current = value;
    });
    return ref.current;
}

export function getStrLen(str, chs = true) {
    let len = 0;
    if (!str) return 0;
    if (!chs) return str.length;
    for (let i = 0; i < str.length; i += 1) {
        if (str.charCodeAt(i) > 127 || str.charCodeAt(i) === 94) {
            len += 2;
        } else {
            len += 1;
        }
    }
    return len;
}
/**
 * 传入一个参数，返回它的数据类型（小写字母）比如: getType(new Date)，返回 date。
 * @param {*} obj
 */
export const getType = obj =>
    Object.prototype.toString
        .call(obj)
        .slice(8, -1)
        .toLowerCase();

/**
 * 人性化显示分钟。。。
 * @param val 分钟
 * @param min 最小刻度：h,m,s
 */
export const showMinues = val => {
    const hours = val / 60;
    const minute = (hours - parseInt(hours, 10)) * 60;
    let str = '';

    if (hours > 0) {
        str += `${parseInt(hours, 10)} 小时 `;
        if (hours - parseInt(hours, 10) > 0) {
            str += `${parseInt(minute, 10)} 分钟 `;
        }
    } else if (minute - parseInt(minute, 10) > 0) {
        str += `${(minute - parseInt(minute, 10)) * 60} 秒`;
    }

    return str;
};

/**
 * 人性化展示时间，默认展示 xx小时xx分钟
 * @param result
 * @param showDay
 * @param showCecond
 * @param timUnit   天单位
 * @returns {string}
 */
export function formatSecond(result, showDay = false, showCecond = false, timUnit = 24) {
    if (!result) return 0;
    const day = parseInt(result / 60 / timUnit, 10);
    const h = showDay
        ? Math.floor((result / 60 / timUnit - parseInt(result / 60 / timUnit, 10)) * timUnit)
        : parseInt(result / 60, 10);
    const m = showCecond ? Math.floor((result / 60 - parseInt(result / 60, 10)) * 60) : parseInt(result % 60, 10);
    const s = Math.floor((result - parseInt(result, 10)) * 60);
    const str = [];

    if (showDay && day > 0) {
        str.push(`${day}天`);
    }
    if (h > 0) {
        str.push(`${h}小时`);
    }
    if (m > 0) {
        str.push(`${m}分钟`);
    }
    if (showCecond && s > 0) {
        str.push(`${s}秒`);
    }

    // 少于等于1秒时
    if (s === 0 && showCecond && result <= 1) {
        str.push(`${(parseFloat(result * 60).toFixed(2) * 100) / 100}秒`);
    }

    return str.length > 0 ? str.join('') : 0;
}

// 显示时长
export const getDuration = (val, unit) => {
    if (!val) return 0;
    let last = '';
    if (unit === 1 || unit === 2) {
        last = `${(val / 60 / 8).toFixed(1)}天`;
    } else {
        last = formatSecond(val);
    }

    return last;
};

// 弹性时长的接口
export const getDurationFlexible = (val, unit) => {
    if (!val || !val.durationLongDays) return 0;
    let last = '';
    if (unit === 1 || unit === 2) {
        last = `${val.durationLongDays}天`;
    } else {
        last = formatSecond(val.durationLong);
    }

    return last;
};

// 清除登录状态
export const clearLoginStates = () => {
    notification.destroy();
    cookie.remove('Authorization');
    localStorage.removeItem('user');
    localStorage.removeItem('loginInfo');
    localStorage.removeItem('currentMail');
    cookie.remove('Authorization');
    localStorage.removeItem('companys');
    pageTabUtil.clearAllTabHistory();
    sessionStorage.removeItem('orgListTableExpandedRowKeys'); // 清除机构管理的列表展开的状态
    if (authHelper) {
        authHelper.clearAuthRoutes();
    }
};

export const exists = (arr, prop, value) => {
    let isExists = false;

    const loop = data => {
        data.forEach(item => {
            if (item[prop] === value) {
                isExists = true;
            } else if (item.children) {
                loop(item.children);
            }
        });
    };

    loop(arr);
    return isExists;
};

export const isCurMonth = date => moment(date).format('YYYY-MM') === moment().format('YYYY-MM');

/**
 * 导出方法
 * @param object {getData:()=>Promise<T>,dataType?:数据类型}
 */
export const download = async ({ getData }) => {
    const res = await getData();
    if (res.data && res.data.type !== 'application/json') {
        const disposition = decodeURI(res.response.headers.get('content-disposition'));
        // attachment; filename=content.txt
        // attachment; filename*=UTF-8''filename.txt
        // attachment; filename="omÃ¡Ã¨ka.jpg"
        // attachment; filename="EURO rates"; filename*=utf-8''%e2%82%ac%20rates
        const filenameRegex = /filename\*?=['"]?(?:UTF-\d['"]*)?([^;\r\n"']*)['"]?;?/gi;
        const matches = filenameRegex.exec(disposition);
        const fileName = matches != null && matches[1] ? matches[1] : '';

        message.success('下载成功');
        FileSaver.saveAs(res.data, fileName);
    } else {
        res.response.json().then(d => {
            message.error(d.msg);
        });
    }
};

export const sub = (str, n) => {
    const str1 = str;
    const r = '/[^\x00-\xff]/g';
    if (str1.replace(r, 'mm').length <= n) {
        return str1;
    }
    const m = Math.floor(n / 2);
    for (let i = m; i < str1.length; i += 1) {
        if (str1.substr(0, i).replace(r, 'mm').length >= n) {
            return `${str1.substr(0, i)}...`;
        }
    }
    return str1;
};

/**
 * const arr = [1, 2, 3, 4]
 * sortArrayByIndex(arr, 1) => [2, 3, 4, 1]
 * @param arr
 * @param index
 * @returns {*}
 */
export const sortArrayByIndex = (arr, index) => arr.slice(index).concat(arr.slice(0, index));

/**
 * 用于全局判断公司来源,为以后方便修改判断
 * 传入公司id  返回这id类型
 */
const countryDict = [
    {
        id: 100,
        name: '微微科技集团',
        area: 'sg'
    },
    {
        id: 101,
        name: '微微科技有限公司',
        area: 'cn'
    },
    {
        id: 1005,
        name: '微微金服信息科技有限公司',
        area: 'cn'
    },
    {
        id: 102,
        name: 'V V Technology Pte Ltd',
        area: 'sg'
    }
];
export const getOrganization = companyId => countryDict.find(item => companyId === item.id) || '';

export const uploadFileToServer = ({ originFileObj, requestUrl, key = 'file' }) => {
    const formData = new FormData();
    formData.append(key, originFileObj);
    return fetch(requestUrl, {
        method: 'POST',
        headers: {
            Authorization: cookie.get('Authorization')
        },
        body: formData
    });
};

// Conversion router to menu.
export const formatter = (data, parentAuthority, parentName) =>
    data
        .map(item => {
            if (!item.name || !item.path) {
                return null;
            }

            let locale = 'menu';
            if (parentName) {
                locale = `${parentName}.${item.name}`;
            } else {
                locale = `menu.${item.name}`;
            }
            let editName = item.editName || '';
            if (editName) {
                editName = formatMessage({
                    id: parentName ? `${parentName}.${item.editName}` : `menu.${item.editName}`,
                    defaultMessage: item.editName
                });
            }
            let detailName = item.detailName || '';
            if (detailName) {
                detailName = formatMessage({
                    id: parentName ? `${parentName}.${item.detailName}` : `menu.${item.detailName}`,
                    defaultMessage: item.detailName
                });
            }

            const result = {
                ...item,
                name: formatMessage({ id: locale, defaultMessage: item.name }),
                editName,
                detailName,
                locale,
                authority: item.authority || parentAuthority
            };
            if (item.routes) {
                const children = formatter(item.routes, item.authority, locale);
                // Reduce memory usage
                result.children = children;
            }
            delete result.routes;
            return result;
        })
        .filter(item => item);

// 获取页面级path
export const getActualPath = item => {
    let actualPath = item.path;
    const fn = it => {
        if (it.children && it.children.length) {
            fn(it.children[0]);
        } else if (authHelper.checkCode(it.code)) {
            actualPath = it.path;
        }
    };
    fn(item);
    return actualPath;
};

/**
 * 获取网络类型
 */
export const getNetworkType = () => {
    const ua = navigator.userAgent;
    let networkStr = ua.match(/NetType\/\w+/) ? ua.match(/NetType\/\w+/)[0] : 'NetType/other';
    networkStr = networkStr.toLowerCase().replace('nettype/', '');
    let networkType;
    switch (networkStr) {
        case 'wifi':
            networkType = 'wifi';
            break;
        case '4g':
            networkType = '4g';
            break;
        case '3g':
            networkType = '3g';
            break;
        case '3gnet':
            networkType = '3g';
            break;
        case '2g':
            networkType = '2g';
            break;
        default:
            networkType = 'other';
    }
    return networkType;
};

/*
 * 处理服务返回的树结构数据
 * */
export const translateTreeData = (data, fileName) => {
    if (Array.isArray(data) && fileName) {
        return data.map(item => ({
            ...item,
            value: item[fileName.value],
            title: item[fileName.title],
            key: item[fileName.value],
            children: item.children ? translateTreeData(item.children, fileName) : []
        }));
    }
    return [];
};

/**
 * 获取当前用户的组织信息
 */

export const getUserOrgInfo = () => {
    const storeUser = localStorage.getItem('user');
    const user = storeUser ? JSON.parse(storeUser) : {};
    const { firstOrgInfo } = user;
    return firstOrgInfo;
};

/**
 * 获取当前用户的组织信息
 */

export const getUserInfo = () => {
    const storeUser = localStorage.getItem('user');
    return storeUser ? JSON.parse(storeUser) : {};
};

/**
 * 带progress的ajax请求
 * @param {*} url
 * @param {*} opts
 * @param {*} progressCallback
 */
export const XMLFetch = (url, opts, progressCallback) =>
    new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open(opts.method || 'GET', url);
        Object.keys(opts.headers || {}).forEach(key => {
            xhr.setRequestHeader(key, opts.headers[key]);
        });
        xhr.onload = e => {
            const {
                target: { responseText, status }
            } = e;
            resolve({
                text: () => responseText,
                json: () => JSON.parse(responseText) || {},
                status
            });
        };
        xhr.onerror = reject;
        if (xhr.upload && progressCallback) {
            xhr.upload.onprogress = e => {
                const { loaded, total } = e;
                progressCallback(Math.round((loaded / total) * 100));
            };
        }
        xhr.send(opts.body);
    });

/**
 * 递归查询父级类名dom
 * @param {*} dom
 * @param {*} className
 */
export const findParentByClassName = (dom, className) => {
    if (!dom) return document.body;
    if (dom.classList.contains(className)) {
        return dom;
    }
    return findParentByClassName(dom.parentNode, className);
};

/*
 * 生成唯一id
 */
export function genID(length) {
    return Number(
        Math.random()
            .toString()
            .substr(3, length) + Date.now()
    ).toString(36);
}

/**
 * @description 生成统一格式的uuid
 * @param {String} prefix   前缀
 */
export function guid(prefix) {
    let str = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
        const r = Math.ceil(Math.random() * 16);
        const v = c === 'x' ? r : (r && 0x3) || 0x8;
        return v.toString(16);
    });
    if (prefix) {
        str = `${prefix}-${str}`;
    }
    return str;
}

/**
 * @description 判断值是否为数组，如果是数组直接输出数组，否则转换成数组
 * @param {*} input 传入的值
 */
export const toArray = input => {
    if (!input) return [];
    if (Array.isArray(input)) return input;
    return [input];
};

/**
 * 渲染时间范围
 * @param startTime
 * @param endTime
 * @param format
 * @return {null|*}
 */
export const formatDateRange = (startTime, endTime, format = 'YYYY-MM-DD') => {
    if (startTime === '' || !startTime) {
        return null;
    }
    return `${moment(startTime).format(format)} ~ ${endTime ? moment(endTime).format(format) : '至今'}`;
};

/**
 * 三位分节法
 * 1000 -> 1,000
 * @param {*} value
 */
export const formatToThreePart = value => {
    if (Number.isNaN(value)) return '';
    return String(value ?? '').replace(/\B(?=(\d{3})+(?!\d))/g, ',');
};

export const NoToChinese = num => {
    if (!/^\d*(\.\d*)?$/.test(num)) {
        return '';
    }
    const AA = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
    const BB = ['', '十', '百', '千', '万', '亿', '点', ''];
    const a = `${num}`.replace(/(^0*)/g, '').split('.');
    let k = 0;
    let re = '';
    for (let i = a[0].length - 1; i >= 0; i -= 1) {
        switch (k) {
            case 0:
                re = BB[7] + re;
                break;
            case 4:
                if (!new RegExp(`0{4}\\d{${a[0].length - i - 1}}$`).test(a[0])) re = BB[4] + re;
                break;
            case 8:
                re = BB[5] + re;
                // eslint-disable-next-line prefer-destructuring
                BB[7] = BB[5];
                k = 0;
                break;
            default:
                break;
        }
        if (k % 4 === 2 && a[0].charAt(i + 2) !== 0 && a[0].charAt(i + 1) === 0) re = AA[0] + re;
        if (a[0].charAt(i) !== 0) re = AA[a[0].charAt(i)] + BB[k % 4] + re;
        k += 1;
    }
    if (a.length > 1) {
        // 加上小数部分(如果有小数部分)
        re += BB[6];
        for (let i = 0; i < a[1].length; i += 1) re += AA[a[1].charAt(i)];
    }
    return re.startsWith('一十') ? re.substring(1) : re;
};

export const filterMenuData = menuData => {
    if (!menuData) {
        return [];
    }

    /**
     * get SubMenu or Item
     */
    const getSubMenu = item => {
        // doc: add hideChildrenInMenu
        if (item.children && !item.hideChildrenInMenu && item.children.some(child => child.name)) {
            return {
                ...item,
                children: filterMenuData(item.children)
            };
        }
        return item;
    };
    return menuData
        .filter(item => item.name)
        .map(item => check(item.authority, getSubMenu(item)))
        .filter(item => item);
};

/**
 * 获取面包屑映射
 * @param {Object} menuData 菜单配置
 */
export const getBreadcrumbNameMap = menuData => {
    const routerMap = {};

    const flattenMenuData = (data, parent, level = 0) => {
        data.forEach(menuItem => {
            if (menuItem.children) {
                flattenMenuData(menuItem.children, menuItem, level + 1);
            }
            // Reduce memory usage
            // 增加父级关联
            routerMap[menuItem.path] = { ...menuItem, parent, level };
        });
    };
    flattenMenuData(menuData);
    return routerMap;
};

export const parseQuery = query => {
    let obj = {};
    const pattern = new RegExp(/([^=&\s]+)=([^=&\s]+)/, 'g');
    while (pattern.exec(query)) {
        obj = { ...obj, [RegExp.$1]: RegExp.$2 };
    }
    return obj;
};

export const parseLocation = ({ pathname, query }) => {
    if (!pathname.includes('?')) {
        return [pathname, query];
    }
    const pathAry = pathname.split('?');
    return [pathAry[0], parseQuery(pathAry[1])];
};

/**
 * @param {Object} values 要校验的对象，可以是form表单对象
 * @param {Boolean} isIncludeError 包含上传出错项，默认true
 * @param {String} listProp 对象中文件所属字段
 */
export const hasUploading = (values, isIncludeError = true, listProp = 'allFileList') => {
    let flag = false;
    if (typeof values === 'object') {
        Object.values(values).forEach(item => {
            if (typeof item === 'object') {
                item[listProp].forEach(subItem => {
                    if (subItem?.status === 'uploading' || (isIncludeError === true && subItem?.status === 'error')) {
                        flag = true;
                    }
                });
            }
        });
    }
    return flag;
};

/**
 * @description 保存文件到本地
 * @param {String} url 文件的url地址
 * @param {String} filename 文件名称
 */
export const saveFile = (url, filename) => {
    const oReq = new XMLHttpRequest();
    oReq.open('GET', url, true);
    oReq.responseType = 'blob';
    oReq.onload = () => {
        const file = new Blob([oReq.response]);
        FileSaver.saveAs(file, filename);
    };
    oReq.send();
};

export const getUser = () => {
    try {
        return JSON.parse(localStorage.getItem('user'));
    } catch (e) {
        console.log(e);
        return {};
    }
};

export const getTabContainer = () =>
    document.querySelector(
        '#menuTabs > .ant-tabs > .ant-tabs-content > .ant-tabs-tabpane-active > .tab-scroll-context'
    ) || window;
